using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.Experimental.GraphView;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using XLFrame.NodeEditor.Extensions;

namespace XLFrame.NodeEditor
{
    /// <summary>
    /// 需要改成通用输入泛型不会计入右键菜单
    /// </summary>
    public abstract class InputNode<T> : NodeViewBase
    {
        /// <summary>
        /// 输出接口的值
        /// </summary>
        protected PortData outData;

        protected override void InitializeForFirstCreation()
        {
            base.InitializeForFirstCreation();

            var outPort = NodePort.CreateOutputPort<T>("输出").SetPortDataIsSave(true);
            outData = outPort.userData as PortData;
            if (outData != null) outData.Value = default(T);

            AddInputFieldDef();
        }

        protected override void Init()
        {
            base.Init();

            // 隐藏标题和扩展
            titleContainer.style.display = DisplayStyle.None;
            extensionContainer.style.display = DisplayStyle.None;

            // 设置顶部和输入容器的样式
            topContainer.style.height = 20;
            topContainer.style.paddingTop = 0;
            topContainer.style.paddingBottom = 0;

            inputContainer.style.minWidth = 40;
            inputContainer.style.paddingTop = 0;
            inputContainer.style.paddingBottom = 0;

        }

        protected override void OnDataLoadingEnd()
        {
            base.OnDataLoadingEnd();
            
            outData = NodePort.GetOutputPort("输出").GetPortData();
            // 添加输入字段
            AddInputFieldDef((T)outData.Value);
        }

        protected override void OnAddView()
        {
            base.OnAddView();
            // 设置端口样式
            SetOutPortStyle(NodePort.GetOutputPort("输出"));
        }

        /// <summary>
        /// 添加输入字段,默认注册事件和放置
        /// </summary>
        /// <param name="def"></param>
        private void AddInputFieldDef(T def = default)
        {
            var data = AddInputField();
            data.value = def;
            data.RegisterValueChangedCallback(evt =>
            {
                outData.Value = evt.newValue;
                // 如果有连接更新节点位置
                var shuchu = NodePort.GetOutputPort("输出");
                if (shuchu.connections.Count() > 0)
                {
                    ScheduleDelayedAction(() =>
                    {
                        // 更新节点位置
                        float w = inputContainer.layout.width + 40;
                        float h = (layout.height - mainContainer.layout.height) / 2;
                        var inputPort = shuchu.connections.First().input;
                        var minPos = inputPort.ChangeCoordinatesTo(inputPort.node.parent, new Vector2(-w, -h));

                        var dir = Vector2.Distance(this.GetPosition().position, minPos);

                        if (dir < 15)
                        {
                            SetPosition(minPos);
                        }
                    });
                }
            });
            // 注册输入完成的回调
            data.RegisterCallback<FocusOutEvent>(evt =>
            {
                NodeGraphView.DataUpdate();
            });
            
            inputContainer.Add(data);
            inputContainer.style.minWidth = inputContainer.style.minWidth.value.value>data.style.minWidth.value.value? 
                inputContainer.style.minWidth.value.value: data.style.minWidth.value.value+5;

        }

        /// <summary>
        /// 需要子类重写的添加字段方法
        /// </summary>
        /// <returns></returns>
        protected abstract BaseField<T> AddInputField();

        /// <summary>
        /// 设置端口样式
        /// </summary>
        /// <param name="outPort"></param>
        private void SetOutPortStyle(Port outPort)
        {
            outPort.Q<Label>("type").style.display = DisplayStyle.None;
        }
        
    }

    /// <summary>
    /// int类型输入节点
    /// </summary>
    public class InputIntNode : InputNode<int>
    {
        public override string MenuPath => "输入/int";

        protected override BaseField<int> AddInputField() => new IntegerField();
    }

    public class InputLongNode : InputNode<long>
    {
        public override string MenuPath => "输入/int";

        protected override BaseField<long> AddInputField() => new LongField();
    }

    /// <summary>
    /// float类型输入节点
    /// </summary>
    public class InputFloatNode : InputNode<float>
    {
        public override string MenuPath => "输入/float";

        protected override BaseField<float> AddInputField() => new FloatField();
    }

    /// <summary>
    /// string类型输入节点
    /// </summary>
    public class InputStringNode : InputNode<string>
    {
        public override string MenuPath => "输入/string";

        protected override BaseField<string> AddInputField() => new TextField();
    }

    public class InputVector2Node : InputNode<Vector2>
    {
        public override string MenuPath => "输入/Vector2";

        protected override BaseField<Vector2> AddInputField()
        {
            var data = new Vector2Field();
            data.style.minWidth = 80;
            return data;
        }
    }

    public class InputVector3Node : InputNode<Vector3>
    {
        public override string MenuPath => "输入/Vector3";

        protected override BaseField<Vector3> AddInputField()
        {
            var data = new Vector3Field();
            data.style.minWidth = 100;
            return data;
        }
    }

    public class InputVector4Node : InputNode<Vector4>
    {
        public override string MenuPath => "输入/Vector4";

        protected override BaseField<Vector4> AddInputField()
        {
            var data = new Vector4Field();
            data.style.minWidth = 120;
            return data;
        }
    }

    public class InputColorNode : InputNode<Color>
    {
        public override string MenuPath => "输入/Color";

        protected override BaseField<Color> AddInputField()
        {
            var data = new ColorField();
            data.style.minWidth = 40;
            return data;
        }
    }

    public class InputBoolNode : InputNode<bool>
    {
        public override string MenuPath => "输入/bool";

        protected override BaseField<bool> AddInputField()
        {
            var data = new Toggle();
            topContainer.style.height = 17;
            inputContainer.style.width = 40;
            return data;
        }
    }

    public class InputVector2IntNode : InputNode<Vector2Int>
    {
        public override string MenuPath => "输入/Vector2Int";

        protected override BaseField<Vector2Int> AddInputField()
        {
            var data = new Vector2IntField();
            data.style.minWidth = 80;
            return data;
        }
    }

    public class InputVector3IntNode : InputNode<Vector3Int>
    {
        public override string MenuPath => "输入/Vector3Int";

        protected override BaseField<Vector3Int> AddInputField()
        {
            var data = new Vector3IntField();
            data.style.minWidth = 100;
            return data;
        }
    }

    public class InputObjectNode : InputNode<UnityEngine.Object>
    {
        public override string MenuPath => "输入/Unity对象";

        protected override BaseField<UnityEngine.Object> AddInputField()
        {
            var data = new ObjectField();
            data.style.minWidth = 80;
            return data;
        }
    }

}